package org.example;

/**
 * @author zehua
 * @date 2023/11/7 15:05
 * @Description TODO rtsp流实时检查分辨率和比特率; rstp转为本地视频和音频
 * @since V1.1.0
 */
import org.bytedeco.javacv.*;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import static org.bytedeco.flycapture.global.FlyCapture2.FRAME_RATE;

public class RtspStreamProcessor {

    public static void main(String[] args) {
        processRtspStream(RtspInfo.RTSP_URL_CAMERA);
    }
    public volatile static boolean flagRecord = true;
    public static void processRtspStream(String rtspUrl) {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtspUrl);

        try {
            grabber.start();
            int width = grabber.getImageWidth();
            int height = grabber.getImageHeight();
            double frameRate = grabber.getFrameRate();
            long startTime = System.currentTimeMillis();
            long videoSize = 0;  // Accumulate the size of read frames


            int i=0;
            Frame frame;
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-ddHHssSSS");
            String format = simpleDateFormat.format(date);
            System.out.println(format);
            // 处理视频帧  0 表示不录取音频
            processVideoFrame(new File("E:\\test\\video\\test_"+format+".mp4"),width,height,0);
            // 处理音频帧
            processAudioFrame(new File("E:\\test\\video\\testAudio_"+format+".mp3"),grabber.getAudioChannels());
            while ((frame = grabber.grab()) != null) {
                if (frame.image != null) {
                    // 分离图像 仅图像
                    recorder.record(frame);
                } else if (frame.samples != null) {
                    // 分离音频
                    recorderOnlyAudio.record(frame);
                }

                if (flagRecord == false){
                    recorder.stop();
                    recorderOnlyAudio.stop();
                }
                // 尝试断开录制
                if (i > 3800){
                    flagRecord = false;
                }
                i++;
                /**
                 * 获取视频的位数
                 */
//                // 假设frame不为空并且有一个视频帧
              /*  videoSize += frame.image.length;
                // 使用帧的大小和经过的时间计算比特率
                long currentTime = System.currentTimeMillis();
                long timeElapsed = currentTime - startTime;

                if (timeElapsed > 0) {  // 避免被零除
                    long bitRate = (videoSize * 8) / (timeElapsed / 1000);  // 每秒位数
                    System.out.printf("Resolution: %dx%d, Bitrate: %d bits/s%n", width, height, bitRate);
                }

                // 您可以在此处处理该帧（例如，显示它或执行分析）
                if ((currentTime - startTime) > 10000) {  // Stop after 10 seconds
                    break;
                }*/
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                try {
                    recorder.stop();
                    recorder.close();
                } catch (FrameRecorder.Exception e) {
                    e.printStackTrace();
                }
                grabber.close();
            } catch (FFmpegFrameGrabber.Exception e) {
                e.printStackTrace();
            } catch (FrameGrabber.Exception e) {
                e.printStackTrace();
            }
        }
    }

    public volatile static FFmpegFrameRecorder recorder = null;
    public volatile static FFmpegFrameRecorder recorderOnlyAudio = null;
    /**
     * 频帧处理代码
     * demo 录视频
     */
    private static void processVideoFrame( File outFile,int imageWidth,int imageHeight,int audioChannels) {
        try {
            recorder = new FFmpegFrameRecorder(outFile, imageWidth, imageHeight, audioChannels);
            recorder.setFormat("mp4");
            recorder.setFrameRate(FRAME_RATE);
            // 录制视频的编码器
            recorder.setVideoCodecName("libx264");
            /**
             * 在FFmpeg中，preset 参数决定了编码视频时使用的算法和压缩比例。不同的预设将影响编码的时间和输出视频流的压缩效率。预设值从最慢到最快依次是：
             * ultrafast
             * superfast
             * veryfast
             * faster
             * fast
             * medium — 编码器的默认值
             * slow
             * slower
             * veryslow
             * 预设越慢，编码器就有更多的时间来分析数据（可能提高压缩率，减少文件大小），但是编码过程需要的时间更长。相对的，更快的预设减少了编码时间，但可能会增加输出文件的大小，并可能略微降低质量。
             * 因此，使用 "fast" 预设是在速度和压缩效率之间取得平衡的选择。在流媒体或实时编码的情况下，人们可能会倾向于使用较快的预设来减少延迟。
             */
            recorder.setVideoOption("preset", "fast");
//            recorder.setPixelFormat(AV_PIX_FMT_YUV420P);
            recorder.start();
        } catch (FFmpegFrameRecorder.Exception e) {
            e.printStackTrace();
        }
    }



    private static final int AUDIO_BITRATE = 192000; // 音频比特率
    private static final int SAMPLE_RATE = 44100; // 采样率
    /**
     * 音频帧处理代码逻辑
     * @param outFile 输出文件
     * @param audioChannels
     */
    private static void processAudioFrame(File outFile,int audioChannels) {

        try {
            // 初始化音频录制器
            recorderOnlyAudio = new FFmpegFrameRecorder(outFile, audioChannels);
            recorderOnlyAudio.setAudioOption("crf", "0");
            recorderOnlyAudio.setAudioQuality(0);
            recorderOnlyAudio.setAudioBitrate(AUDIO_BITRATE);
            recorderOnlyAudio.setSampleRate(SAMPLE_RATE);
            recorderOnlyAudio.setAudioChannels(audioChannels);
            recorderOnlyAudio.setAudioCodecName("libmp3lame"); // 设置音频编码器
            recorderOnlyAudio.start();
        } catch (FFmpegFrameRecorder.Exception e) {
            e.printStackTrace();
        }

    }
}

